﻿using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Zhongjiu.AuthHelper;
using Zhongjiu.AuthHelper.OverWrite;
using Zhongjiu.Common;
using Zhongjiu.IServices;
using Zhongjiu.Model;

namespace Zhongjiu.CollectMoney.Api
{
  /// <summary>
  /// 登录管理【无权限】
  /// </summary>
  [Produces("application/json")]
  [Route("api/Login")]
  [AllowAnonymous]
  public class LoginController : BaseApiController
  {
    readonly ISysUserInfoServices _sysUserInfoServices;
    readonly IUserRoleServices _userRoleServices;
    readonly IRoleServices _roleServices;
    readonly PermissionRequirement _requirement;
    private readonly IRoleModulePermissionService _roleModulePermissionServices;


    /// <summary>
    /// 构造函数注入
    /// </summary>
    /// <param name="sysUserInfoServices"></param>
    /// <param name="userRoleServices"></param>
    /// <param name="roleServices"></param>
    /// <param name="requirement"></param>
    /// <param name="roleModulePermissionServices"></param>
    public LoginController(ISysUserInfoServices sysUserInfoServices, IUserRoleServices userRoleServices, IRoleServices roleServices, PermissionRequirement requirement, IRoleModulePermissionService roleModulePermissionServices)
    {
      this._sysUserInfoServices = sysUserInfoServices;
      this._userRoleServices = userRoleServices;
      this._roleServices = roleServices;
      _requirement = requirement;
      _roleModulePermissionServices = roleModulePermissionServices;
    }


    #region 获取token的第1种方法
    /// <summary>
    /// 获取JWT的方法1
    /// </summary>
    /// <param name="name"></param>
    /// <param name="pass"></param>
    /// <returns></returns>
    [HttpGet]
    [Route("Token")]
    public async Task<MessageModel<string>> GetJwtStr(string name, string pass)
    {

      string jwtStr = string.Empty;
      bool suc = false;
      //这里就是用户登陆以后，通过数据库去调取数据，分配权限的操作

      var user = await _sysUserInfoServices.GetUserRoleNameStr(name, MD5Helper.MD5Encrypt32(pass));
      if (user != null)
      {

        TokenModelJwt tokenModel = new TokenModelJwt { Uid = 1, Role = user };

        jwtStr = JwtHelper.IssueJwt(tokenModel);
        suc = true;
      }
      else
      {
        jwtStr = "login fail!!!";
      }

      return new MessageModel<string>()
      {
        IsSuccess = suc,
        Msg = suc ? "获取成功" : "获取失败",
        Data = jwtStr
      };
    }


    /// <summary>
    /// 获取JWT的方法2：给Nuxt提供
    /// </summary>
    /// <param name="name"></param>
    /// <param name="pass"></param>
    /// <returns></returns>
    [HttpGet]
    [Route("GetTokenNuxt")]
    public MessageModel<string> GetJwtStrForNuxt(string name, string pass)
    {
      string jwtStr = string.Empty;
      bool suc = false;
      //这里就是用户登陆以后，通过数据库去调取数据，分配权限的操作
      //这里直接写死了
      if (name == "admins" && pass == "admins")
      {
        TokenModelJwt tokenModel = new TokenModelJwt
        {
          Uid = 1,
          Role = "Admin"
        };

        jwtStr = JwtHelper.IssueJwt(tokenModel);
        suc = true;
      }
      else
      {
        jwtStr = "login fail!!!";
      }
      var result = new
      {
        data = new { success = suc, token = jwtStr }
      };

      return new MessageModel<string>()
      {
        IsSuccess = suc,
        Msg = suc ? "获取成功" : "获取失败",
        Data = jwtStr
      };
    }
    #endregion



    /// <summary>
    /// 获取JWT的方法3：整个系统主要方法
    /// </summary>
    /// <param name="name"></param>
    /// <param name="pass"></param>
    /// <returns></returns>
    [HttpGet]
    [Route("JWTToken3.0")]
    public async Task<MessageModel<TokenInfoViewModel>> GetJwtToken3(string name = "", string pass = "")
    {
      string jwtStr = string.Empty;

      if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(pass))
        return Failed<TokenInfoViewModel>("用户名或密码不能为空");

      pass = MD5Helper.MD5Encrypt32(pass);

      var user = await _sysUserInfoServices.Query(d => d.LoginName == name && d.LoginPWD == pass && d.IsDeleted == false);
      if (user.Count > 0)
      {
        var userRoles = await _sysUserInfoServices.GetUserRoleNameStr(name, pass);
        //如果是基于用户的授权策略，这里要添加用户;如果是基于角色的授权策略，这里要添加角色
        var claims = new List<Claim> {
                    new Claim(ClaimTypes.Name, name),
                    new Claim(JwtRegisteredClaimNames.Jti, user.FirstOrDefault().Id.ToString()),
                    new Claim(ClaimTypes.Expiration, DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString()) };
        claims.AddRange(userRoles.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));


        // ids4和jwt切换
        // jwt
        if (!Permissions.IsUseIds4)
        {
          var data = await _roleModulePermissionServices.RoleModuleMaps();
          var list = (from item in data
                      where item.IsDeleted == false
                      orderby item.Id
                      select new PermissionItem
                      {
                        Url = item.Module?.LinkUrl,
                        Role = item.Role?.Name.ObjToString(),
                      }).ToList();

          _requirement.Permissions = list;
        }

        var token = JwtToken.BuildJwtToken(claims.ToArray(), _requirement);
        return Success(token, "获取成功");
      }
      else
      {
        return Failed<TokenInfoViewModel>("认证失败");
      }
    }

    /// <summary>
    /// 请求刷新Token（以旧换新）
    /// </summary>
    /// <param name="token"></param>
    /// <returns></returns>
    [HttpGet]
    [Route("RefreshToken")]
    public async Task<MessageModel<TokenInfoViewModel>> RefreshToken(string token = "")
    {
      string jwtStr = string.Empty;

      if (string.IsNullOrEmpty(token))
        return Failed<TokenInfoViewModel>("token无效，请重新登录！");
      var tokenModel = JwtHelper.SerializeJwt(token);
      if (tokenModel != null && JwtHelper.customSafeVerify(token) && tokenModel.Uid > 0)
      {
        var user = await _sysUserInfoServices.QueryById(tokenModel.Uid);
        if (user != null)
        {
          var userRoles = await _sysUserInfoServices.GetUserRoleNameStr(user.LoginName, user.LoginPWD);
          //如果是基于用户的授权策略，这里要添加用户;如果是基于角色的授权策略，这里要添加角色
          var claims = new List<Claim> {
                    new Claim(ClaimTypes.Name, user.LoginName),
                    new Claim(JwtRegisteredClaimNames.Jti, tokenModel.Uid.ObjToString()),
                    new Claim(ClaimTypes.Expiration, DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString()) };
          claims.AddRange(userRoles.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));

          //用户标识
          var identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme);
          identity.AddClaims(claims);

          var refreshToken = JwtToken.BuildJwtToken(claims.ToArray(), _requirement);
          return Success(refreshToken, "获取成功");
        }
      }
      return Failed<TokenInfoViewModel>("认证失败！");
    }

    //public async Task<MessageModel<TokenInfoViewModel>> GetToken(string managerName,string pwd = "")
    //{
    //  string.IsNullOrEmpty(managerName).TrueThrow("用户名不能为空");
    //  string.IsNullOrEmpty(pwd).TrueThrow("密码不能为空");

    //}
    /// <summary>
    /// 获取JWT的方法4：给 JSONP 测试
    /// </summary>
    /// <param name="callBack"></param>
    /// <param name="id"></param>
    /// <param name="sub"></param>
    /// <param name="expiresSliding"></param>
    /// <param name="expiresAbsoulute"></param>
    /// <returns></returns>
    [HttpGet]
    [Route("jsonp")]
    public void Getjsonp(string callBack, long id = 1, string sub = "Admin", int expiresSliding = 30, int expiresAbsoulute = 30)
    {
      TokenModelJwt tokenModel = new TokenModelJwt
      {
        Uid = id,
        Role = sub
      };

      string jwtStr = JwtHelper.IssueJwt(tokenModel);

      string response = string.Format("\"value\":\"{0}\"", jwtStr);
      string call = callBack + "({" + response + "})";
      Response.WriteAsync(call);
    }


    /// <summary>
    /// 测试 MD5 加密字符串
    /// </summary>
    /// <param name="password"></param>
    /// <returns></returns>
    [HttpGet]
    [Route("Md5Password")]
    public string Md5Password(string password = "")
    {
      return MD5Helper.MD5Encrypt32(password);
    }

    /// <summary>
    /// swagger登录
    /// </summary>
    /// <param name="loginRequest"></param>
    /// <returns></returns>
    [HttpPost]
    [Route("/api/Login/swgLogin")]
    public dynamic SwgLogin([FromBody] SwaggerLoginRequest loginRequest)
    {
      // 这里可以查询数据库等各种校验
      if (loginRequest?.name == "admin" && loginRequest?.pwd == "admin")
      {
        HttpContext.Session.SetString("swagger-code", "success");
        return new { result = true };
      }

      return new { result = false };
    }

    /// <summary>
    /// weixin登录
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    [Route("wxLogin")]
    public dynamic WxLogin(string g = "", string token = "")
    {
      return new { g, token };
    }
  }

  public class SwaggerLoginRequest
  {
    public string name { get; set; }
    public string pwd { get; set; }
  }
}